﻿using System;
using System.Diagnostics;
using System.Threading;
using BenchmarkDotNet.Attributes;
using BenchmarkDotNet.Jobs;

namespace NLuaBenchmarkDotNetTest.Timer
{
    [MemoryDiagnoser]
    public class TimerBenchmarks
    {
        [Params(100)]  // 测试间隔(ms)
        public int Interval { get; set; } = 100;

        [Params(1000, 5000)]  // 测试时长(ms)
        public int Duration { get; set; } = 5000;

        private volatile int _elapsedCount;
        private Stopwatch _globalStopwatch;
        private ManualResetEventSlim _testCompleteEvent;

        [Benchmark(Baseline = true)]
        public int SystemTimersTimer()
        {
            _elapsedCount = 0;
            _testCompleteEvent = new ManualResetEventSlim();
            _globalStopwatch = Stopwatch.StartNew();

            using (var timer = new System.Timers.Timer(Interval))
            {
                timer.Elapsed += (s, e) => OnElapsed(timer);
                timer.Start();

                _testCompleteEvent.Wait();
            }

            return _elapsedCount;
        }

        [Benchmark]
        public int SystemThreadingTimer()
        {
            _elapsedCount = 0;
            _testCompleteEvent = new ManualResetEventSlim();
            _globalStopwatch = Stopwatch.StartNew();

            using (var timer = new System.Threading.Timer(_ => OnElapsed(),
                       null, 0, Interval))
            {
                _testCompleteEvent.Wait();
            }

            return _elapsedCount;
        }

        private void OnElapsed(System.Timers.Timer timer = null)
        {
            // 确保所有写入操作完成后才增加计数
            Interlocked.MemoryBarrier();

            var newCount = Interlocked.Increment(ref _elapsedCount);
            var elapsedMs = _globalStopwatch.ElapsedMilliseconds;

            // 精确结束条件：达到测试时长时停止
            if (elapsedMs >= Duration)
            {
                // 记录最终计数前插入内存屏障
                Interlocked.MemoryBarrier();

                if (timer != null)
                    timer.Stop();

                _testCompleteEvent.Set();
            }
        }

        // 添加理论值参考（可选）
        [Benchmark]
        public int TheoreticalCount() => Duration / Interval;
    }
}